home *** CD-ROM | disk | FTP | other *** search
- /* bt_ins.c - insert function */
- #include "stdio.h"
- #include "btree.h"
- #include "bt_macro.h"
-
- extern IX_DESC *pci ; /* refers to index descriptor */
- /* for current function call */
- extern BLOCK spare_block ; /* scratch block for splits and */
- /* compressing */
- extern int split_size ; /* treshold for splitting the block */
-
- int insert_ix(pe,pix) /* find first entry with key */
- ENTRY *pe ; /* points to key to be matched */
- /* store the rec. loc. here */
- IX_DESC *pix ; /* points to index descriptor */
- { /* returns success=1, failure=0 */
- int ret ;
- BLOCK b ;
-
- pci = pix ;
- ret = ins_level(0,pe,&b) ; /* insert entry at leafe level */
-
- if( ret == IX_OK ) /* if the insertion worked */
- next_ix(0,&b) ; /* move past entry inserted */
-
- return ( ret ) ; /* return success / failure */
- }
-
-
- int ins_level(l,pe,pb) /* insert an entry at */
- int l ; /* this level */
- ENTRY *pe ; /* points to entry */
- BLOCK *pb ;
- {
- RECPOS r ;
- int ret ;
-
- if( l >= pci->dx.nl ) /* do we need a new level ? */
- return( IX_FAIL ) ; /* yes - overflow */
-
- retrieve_block(l,CB(l),pb,CURR) ;
- /* does it fit into the block ? */
- if( (pb->bend + ENT_SIZE(pe)) <= split_size )
- { ins_block(pb,pe,CO(l)) ; /* yes - put entry into block */
- update_block(pb) ;
- ret = IX_OK ;
- }
- else ret = split(l,pe,pb) ; /* no - split the block */
-
- return( ret ) ;
- }
-
- int split(l,pe,pb) /* split a block into two */
- int l ;
- ENTRY *pe ;
- BLOCK *pb ;
- {
- int half, ins_pos, last, ret ;
- BLOCK *pbb ;
- ENTRY e ;
-
- ins_pos = CO(l) ; /* remember where insert was */
-
- if( (l+1) >= pci->dx.nl ) /* check for top level */
- return( IX_FAIL ) ; /* (can't split top level block) */
-
- /* allocate a big block */
- pbb = (BLOCK *) calloc(sizeof(BLOCK)+sizeof(ENTRY),1) ;
- if( pbb == NULL ) /* did allocation fail ? */
- return( IX_FAIL ) ; /* yes - exit */
-
- /* do insert in big block */
- pbb->bend = 0 ;
- combine(pb,pbb) ; /* copy contents of old buffer */
- ins_block(pbb,pe,CO(l)) ; /* insert new entry */
-
- /* now find where to split */
- /* no more than 1/2 in left block */
- last = scan_blk(pbb,pbb->bend/2) ; /* start of last entry */
- /* in left half o bib block */
- half = next_entry(pbb,last) ; /* end of left half */
- /* allocate disk space for left block */
- if( get_block(l,pbb) == IX_FAIL ) /* check for failure */
- { free(pbb) ;
- return( IX_FAIL ) ;
- }
- /* make an entry for the new block */
- /* on the upper level */
- copy_entry(&e,ENT_ADR(pbb,last) ) ;
- e.rptr = pbb->brec ; /* point entry to left block */
-
- ret = ins_level(l+1,&e,pb) ; /* inserting new index entry */
- /* for left block at higher level */
- /* ( this makes the l+1 position */
- /* point to the left block ) */
- if( ret != IX_OK ) /* check for higher level failure */
- { free(pbb) ; /* yes - free big block area */
- put_free(pbb) ; /* free new index block */
- return( ret ) ; /* return failure code */
- }
-
- /* use pb for right block */
- mover(ENT_ADR(pb,0),ENT_ADR(pbb,half),pbb->bend-half) ;
- pb->bend = pbb->bend - half ;
- pb->brec = CB(l) ; /* restore blosk's location */
- pb->lvl = l ; /* and it's level */
- update_block(pb) ; /* and update left block */
-
- /* adjust current position */
- if( ins_pos >= half ) /* is curr entry in left or right */
- { CO(l) = CO(l) - half ; /* right - and adjust offset */
- next_ix(l+1,pb) ; /* upper level pos. */
- }
- else CB(l) = e.rptr ; /* left - make left block current */
- free(pbb) ; /* free the big scratch block */
-
- return( ret ) ;
- }
-
-
-